package cn.reinforce.util.aliyun;

import cn.reinforce.util.aliyun.model.opensearch.SuggestResult;
import cn.reinforce.util.aliyun.model.opensearch.Suggestion;
import com.aliyun.opensearch.SearcherClient;
import com.aliyun.opensearch.sdk.dependencies.com.google.common.collect.Lists;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchClientException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchException;
import com.aliyun.opensearch.sdk.generated.search.Config;
import com.aliyun.opensearch.sdk.generated.search.Order;
import com.aliyun.opensearch.sdk.generated.search.SearchFormat;
import com.aliyun.opensearch.sdk.generated.search.SearchParams;
import com.aliyun.opensearch.sdk.generated.search.Sort;
import com.aliyun.opensearch.sdk.generated.search.SortField;
import com.aliyun.opensearch.sdk.generated.search.Suggest;
import com.aliyun.opensearch.sdk.generated.search.general.SearchResult;
import com.aliyun.opensearch.search.SearchParamsBuilder;
import com.aliyun.opensearch.search.SearchResultDebug;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.util.List;

/**
 * 阿里云开放搜索工具
 * @author 幻幻Fate
 * @create 2019/12/4
 * @since
 */
public class AliyunOpenSearchUtil {

    /**
     * 搜索
     *
     * @param keyword  关键字
     * @param pageNum  页码
     * @param pageSize 每页条数
     * @return
     * @throws OpenSearchClientException
     * @throws OpenSearchException
     */
    public static String search(String keyword, int pageNum, int pageSize) throws OpenSearchClientException, OpenSearchException {
        Aliyun aliyun = Aliyun.INSTANCE;
        //创建SearcherClient对象，并以OpenSearchClient对象作为构造参数
        SearcherClient searcherClient = new SearcherClient(aliyun.getOpenSearchClient());
        //定义Config对象，用于设定config子句参数，指定应用名，分页，数据返回格式等等
        Config config = new Config(Lists.newArrayList(aliyun.getAppName()));

        config.setStart((pageNum - 1) * pageSize);
        config.setHits(pageSize);
        //设置返回格式为fulljson格式
        config.setSearchFormat(SearchFormat.JSON);
        // 创建参数对象
        SearchParams searchParams = new SearchParams(config);
        // 指定搜索的关键词，这里要指定在哪个索引上搜索，如果不指定的话默认在使用“default”索引（索引字段名称是您在您的数据结构中的“索引字段列表”中对应字段。），若需多个索引组合查询，需要在setQuery处合并，否则若设置多个setQuery子句，则后面的子句会替换前面子句
        searchParams.setQuery("default:'" + keyword + "'");
        //设置查询过滤条件
//        searchParams.setFilter("id>0");
        //创建sort对象，并设置二维排序
        Sort sort = new Sort();
        //降序
        sort.addToSortFields(new SortField("publish_date", Order.DECREASE));
        //若id相同则以RANK相关性算分升序
//        sort.addToSortFields(new SortField("RANK", Order.INCREASE));
        //执行查询语句返回数据对象
        SearchResult searchResult = searcherClient.execute(searchParams);
        //以字符串返回查询数据
        String result = searchResult.getResult();

        return result;
    }

    /**
     * 获取OpenSearch的Suggest
     *
     * @param query 关键字
     * @return
     */
    public static List<Suggestion> suggest(String query, String suggestName) {
        Aliyun aliyun = Aliyun.INSTANCE;
        //定义Config对象，用于设定config子句参数，分页或数据返回格式，指定应用名等等
        Config config = new Config(Lists.newArrayList(aliyun.getAppName()));
        config.setStart(0);
        config.setHits(8);
        //设置返回格式为json，3.1.2 sdk只支持返回xml和json格式，暂不支持返回fulljson类型，3.1.3版本支持fulljson
        config.setSearchFormat(SearchFormat.JSON);
        // 设置查询子句，若需多个索引组合查询，需要setQuery处合并，否则若设置多个setQuery后面的会替换前面查询
        SearchParams searchParams = new SearchParams(config);
        Suggest suggest = new Suggest(suggestName);
        searchParams.setSuggest(suggest);//searchParams对象添加下拉对象
        searchParams.setQuery(query);//在控制台中下拉列表中如果能搜出"nihao"，这里也能够搜出
        // SearchParams的工具类，提供了更为便捷的操作
        SearchParamsBuilder paramsBuilder = SearchParamsBuilder.create(searchParams);
        // 执行返回查询结果
        SearchResult searchResult;
        try {
            SearcherClient searcherClient = new SearcherClient(aliyun.getOpenSearchClient());
            searchResult = searcherClient.execute(paramsBuilder);
            String result = searchResult.getResult();

            Gson gson = new GsonBuilder().create();

            SuggestResult suggestResult = gson.fromJson(result, SuggestResult.class);

            if (suggestResult.getErrors() != null && !suggestResult.getErrors().isEmpty()) {
                System.out.println("error code:" + suggestResult.getErrors().get(0).getCode());
                System.out.println("error message:" + suggestResult.getErrors().get(0).getMessage());
            } else {
                //个别用户可能需要debug请求地址信息
                SearchResultDebug srd = searcherClient.executeDebug(searchParams);
                System.out.println(srd.getRequestUrl().toString());
                return suggestResult.getSuggestions();
            }
        } catch (OpenSearchException e) {
            e.printStackTrace();
        } catch (OpenSearchClientException e) {
            e.printStackTrace();
        }
        return null;
    }
}
